﻿
namespace MathProvider

    [<AutoOpen>]
    module Profile =
       type Watcher() =
           let stopWatch = new System.Diagnostics.Stopwatch()
           member m.tic() =
               stopWatch.Reset()
               stopWatch.Start()
           member m.toc() =
               stopWatch.Stop()
               printfn "passed: %f ms" stopWatch.Elapsed.TotalMilliseconds
               stopWatch.Reset()
               stopWatch.Start()
           member m.toc(msg) =
               stopWatch.Stop()
               printfn "%s: %f ms" msg stopWatch.Elapsed.TotalMilliseconds
               stopWatch.Reset()
               stopWatch.Start()

       let getWatch() = new Watcher()

       let private stopWatch = getWatch()
       let tic() = stopWatch.tic()
       let toc(msg:string) = stopWatch.toc(msg)

    module LinearAlgebra = 
        open Microsoft.FSharp.Math
        open Microsoft.FSharp.Math.Experimental

        let NYI() = failwith "not implemented yet"

        let startProvider() = 
            let isSucc = Experimental.LinearAlgebra.Lapack.Start()
            printfn "Fatlab: dense linear algebra service = %A" (if isSucc then "Native Lapack" else "Managed code")

        let mutable r = new System.Random()
        let resetRandom seed = 
            r <- new System.Random(seed)

        /// dense matrix functions

        let svd = LinearAlgebra.SVD
        let qr = LinearAlgebra.QR
        let lu = LinearAlgebra.LU
        let chol = LinearAlgebra.Cholesky
        let cond = LinearAlgebra.Condition
        let det = LinearAlgebra.Determinant
        let inv = LinearAlgebra.Inverse
        let solve = LinearAlgebra.SolveLinearSystem
        let mm = LinearAlgebra.MM

        let rand n m = 
            Matrix.init n m (fun i j -> r.NextDouble() )
            
        
        // TODO: change transpose in the mathprovider wrapper
        let eigenSym m = 
            let v,e = LinearAlgebra.EigenSpectrumWhenSymmetric m
            v, e.Transpose

        let cov (m1:matrix) (m2:matrix) = mm (m1.Transpose) m2
       
        
        /// sparse matrix functions
        let svds() = NYI()
    


        (* test code
        let a = matrix [[1.;2.;3.]; [2.;3.;4.]]
        let b = a.Transpose * a
        eigenSym b

        *)


